package com.mssh.login.core;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mssh.entity.table.SysUser;
import com.mssh.login.mapper.SysUserMapper;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: 熳殊沙华
 * @Date: 2025/03/25/11:43
 * @Description:
 */
public class JwtRealm extends AuthorizingRealm {

    private SysUserMapper sysUserMapper;

    // 方式1：构造器注入（推荐）
    public JwtRealm(SysUserMapper sysUserMapper) {
        this.sysUserMapper = sysUserMapper;
    }

    /**
     * 授权（权限校验时调用）
     * @param principals
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //获取令牌对象
        SysUser user = (SysUser) principals.getPrimaryPrincipal();
        //查询用户对应角色标识
        List<String> roleLabels = sysUserMapper.findRoleLabelsList(user.getId());
        //查询用户对应的资源标识
        List<String> permissions = sysUserMapper.findPermissionsList(user.getId());
        //构建鉴权信息对象
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //添加该用户所有的角色
        simpleAuthorizationInfo.addRoles(roleLabels);
        //添加该用户所有的资源标识，资源表中的lable字段为权限标识，可以配合@RequiresPermissions({lable})注解进行权限控制
        simpleAuthorizationInfo.addStringPermissions(permissions);
        return simpleAuthorizationInfo;
    }

    /**
     * 认证（登录时调用）
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String account = upToken.getUsername();
        // 实际开发中需查询数据库验证用户是否存在
        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
        wrapper.eq("account", account);
        List<SysUser> list = sysUserMapper.selectList(wrapper);
        if(list == null || list.size() != 1){
            throw new UnknownAccountException("用户不存在！");
        }
        SysUser user = list.get(0);
        //构建认证对象信息 1、令牌对象 2、密文密码 3、加密因子（盐，转成bytes） 4、当前Realm的名称
        String salt = user.getSalt();
        String password =  user.getPassword();
        return new SimpleAuthenticationInfo(user, password, ByteSource.Util.bytes(salt), getName());
    }
}
